<?php

namespace Core;

/**
 * Class Logger
 *
 * 一个简单的静态文件日志记录器。
 * 提供 info 和 error 级别的日志记录。
 *
 * @package Core
 */
class Logger
{
    /**
     * @var string 日志文件的完整路径。
     *
     * !! 安全警告 !!
     * 日志文件不应存储在 'public' 目录或任何可通过 Web 访问的位置。
     * 推荐将其存储在项目根目录下的 'storage' 或 'var/log' 目录中。
     *
     * 假设当前目录是 /project-root/src/Core/
     * 那么 __DIR__ . '/../../storage/logs/app.log' 将指向 /project-root/storage/logs/app.log
     */
    protected static string $logFile = __DIR__ . '/../../storage/logs/app.log';

    /**
     * 记录一条 "INFO" 级别的消息。
     *
     * @param mixed $message 要记录的消息（可以是字符串、数组或对象）
     * @return void
     */
    public static function info(mixed $message): void
    {
        self::writeLog('INFO', $message);
    }

    /**
     * 记录一条 "ERROR" 级别的消息。
     *
     * @param mixed $message 要记录的错误（可以是字符串、数组、对象或异常）
     * @return void
     */
    public static function error(mixed $message): void
    {
        // 如果是异常，获取更详细信息
        if ($message instanceof \Throwable) {
            $message = sprintf(
                "Exception '%s' with message '%s' in %s:%d\nStack trace:\n%s",
                get_class($message),
                $message->getMessage(),
                $message->getFile(),
                $message->getLine(),
                $message->getTraceAsString()
            );
        }
        
        self::writeLog('ERROR', $message);
    }

    /**
     * 将格式化的日志条目写入文件。
     *
     * @param string $level 日志级别 (e.g., 'INFO', 'ERROR')
     * @param mixed $message 要记录的消息
     * @return void
     */
    protected static function writeLog(string $level, mixed $message): void
    {
        try {
            // 确保日志目录存在
            $logDir = dirname(self::$logFile);
            if (!is_dir($logDir)) {
                // 安全：使用 0755 权限创建目录
                mkdir($logDir, 0755, true);
            }

            // 确保日志文件存在且可写
            if (!file_exists(self::$logFile)) {
                touch(self::$logFile);
                // 安全：使用 0644 权限
                chmod(self::$logFile, 0644);
            }

            // 健壮性：如果消息是数组或对象，则序列化
            if (!is_string($message)) {
                $message = print_r($message, true);
            }

            // 格式化日志条目
            $date = date('Y-m-d H:i:s');
            $formatted = "[$date][$level] $message" . PHP_EOL;

            // 安全：使用 FILE_APPEND 和 LOCK_EX（排他锁）写入文件
            file_put_contents(
                self::$logFile,
                $formatted,
                FILE_APPEND | LOCK_EX
            );

        } catch (\Exception $e) {
            // 健壮性：如果日志记录失败（例如权限问题、磁盘已满），
            // 触发一个 PHP 错误，而不是让应用程序崩溃。
            trigger_error(
                "Logger Error: Failed to write to log file. Error: " . $e->getMessage(),
                E_USER_WARNING
            );
        }
    }
}